<?php

namespace app\admin\model\order;

use app\model\MovieOrder;
use app\ymsh\model\Order;
use think\facade\Db;
use think\facade\Log;
use app\common\model\Export;
use app\common\model\FinanceStat;

class Movie
{
    private $table = 'movie_order';
    private $error = '';

    /**
     * 列表.
     */
    public function getList($params)
    {
        $where = [];
        $where[] = ['status', '=', 2];
        $agentName = $params['agent_name'] ?? '';
        if ($agentName) {
            $agentId = Db::name('agent')
                ->where('username|company_name', 'like', '%' . $agentName . '%')
                ->column('id');
            if ($agentId) {
                $where[] = ['agent_id', 'in', $agentId];
            } else {
                $where[] = ['agent_id', '=', -1];
            }
        }
        $orderId = trim($params['order_id'] ?? '');
        if ($orderId) {
            $where[] = ['order_id|supplier_order_id', '=', $orderId];
        }
        if (!empty($params['supplier_status'])) {
            if ($params['supplier_status'] == 1) { // 待出票
                $where[] = ['supplier_status', 'in', [1, 2, 3]];
            } elseif ($params['supplier_status'] == 2) { // 已出票
                $where[] = ['supplier_status', 'in', [4, 5]];
            } elseif ($params['supplier_status'] == 3) { // 已取消
                $where[] = ['supplier_status', '=', 10];
            } elseif ($params['supplier_status'] == 4) { // 已结算
                $where[] = ['settle_status', '=', 3];
            }
        }
        if (!empty($params['created_at'])) {
            $params['created_at'][1] .= ' 23:59:59';
            $where[] = ['created_at', 'between', $params['created_at']];
        }
        //结算时间
        if (!empty($params['settle_time'])) {
            $settle_time_search = [strtotime($params['settle_time'][0]), strtotime($params['settle_time'][1] .= ' 23:59:59')];
            $where[] = ['settle_time', 'between', $settle_time_search];
        }
        $paginate = [
            'page' => $params['page'] ?? 1,
            'list_rows' => $params['list_rows'] ?? 10,
        ];

        if (!empty($params['is_export'])) {
            // 返回导出 excel 需要的数据
            $list = MovieOrder::query()
                ->withSearch(['app_id','merchant_id'],request()->all())
                ->with((new Order())->getWith())
                ->where($where)
                ->order('id desc')
                ->select()
                ->toArray();
            $agentIds = array_column($list, 'agent_id');
            $supplierIds = array_column($list, 'supplier_id');
        } else {
            $list = MovieOrder::query()
                ->withSearch(['app_id','merchant_id'],request()->all())
                ->with((new Order())->getWith())
                ->where($where)
                ->append(['settle_time_text', 'channel_name'])
                ->order('id desc')
                ->paginate($paginate)
                ->toArray();
            $agentIds = array_column($list['data'], 'agent_id');
            $supplierIds = array_column($list['data'], 'supplier_id');
        }
        if ($agentIds) {
            $agent = Db::name('agent')
                ->whereIn('id', $agentIds)
                ->column('username, company_name', 'id');
        }
        if ($supplierIds) {
            $supplier = Db::name('base_supplier')
                ->whereIn('id', $supplierIds)
                ->column('name', 'id');
        }

        // 导出数据字段处理
        if (!empty($params['is_export'])) {
            $res = [];
            $title = ['系统订单号', '电影名称', '放映时间', '订单金额', '成本价', '平台利润', '代理商利润', '状态', '下单时间', '代理商用户名', '代理商公司名称', '供应商'];
            $statusMap = [
                4 => '已出票',
                5 => '已出票',
                10 => '已取消',
            ];
            foreach ($list as $v) {
                $res[] = [
                    $v['order_id'] . "\t",
                    $v['film_name'],
                    $v['show_time'] . ' ~ ' . $v['end_time'],
                    fen2yuan($v['sale_price']) . '',
                    fen2yuan($v['supplier_price']) . '',
                    fen2yuan($v['platform_profit']) . '',
                    fen2yuan($v['profit']) . '',
                    $statusMap[$v['supplier_status']] ?? '出票中',
                    $v['created_at'],
                    $agent[$v['agent_id']]['username'] ?? '',
                    $agent[$v['agent_id']]['company_name'] ?? '',
                    $supplier[$v['supplier_id']] ?? '',
                ];
            }
            unset($list);
            $export = new Export;
            $name = '影票订单';
            return $export->downloadExcel($title, $res, $name);
        }

        foreach ($list['data'] as $k => $v) {
            $list['data'][$k]['agent_name'] = $agent[$v['agent_id']]['username'] ?? '';
            $list['data'][$k]['company_name'] = $agent[$v['agent_id']]['company_name'] ?? '';
            $list['data'][$k]['order_id'] = strval($v['order_id']);
            $list['data'][$k]['supplier_name'] = $supplier[$v['supplier_id']] ?? '';
        }
        return success('操作成功', $list);
    }

    /**
     * 退款.
     */
    public function refund($order)
    {
        if (2 != $order['status']) {
            $this->error = '该订单尚未支付';

            return false;
        }
        if (10 != $order['supplier_status']) {
            $this->error = '出票失败的订单才能退款【' . $order['supplier_status'] . '】';

            return false;
        }
        if (2 != $order['refund_status']) {
            $this->error = '退款状态有误【' . $order['refund_status'] . '】';

            return false;
        }

        $res = Db::name($this->table)
            ->where('id', $order['id'])
            ->where('refund_status', 2)
            ->update([
                'refund_status' => 4, // 退款中
            ]);
        if (!$res) {
            $this->error = '退款状态有误' . __LINE__;
            return false;
        }

        $refundFee = 0;
        if ($order['order_from'] == ORDER_FROM_H5) {
            // H5 过来的订单，才有在线支付
            $payLog = Db::name('movie_pay_log')
                ->where('order_id', $order['order_id'])
                ->where('status', 2)
                ->find();
            if (empty($payLog)) {
                $this->error = '支付记录不存在';

                return false;
            }

            $refundFee = $payLog['real_pay_price'] - $payLog['refund_amount'];

            $payLog['refund_fee'] = $refundFee;
            $res = $this->wxpayRefund($payLog);
            if (false === $res) {
                return false;
            }
        }

        Db::startTrans();
        try {
            $res = Db::name($this->table)
                ->where('id', $order['id'])
                ->where('refund_status', 4)
                ->update([
                    'refund_status' => 3,
                ]);
            if (!$res) {
                Db::rollback();

                $this->error = '退款失败：重复退款';
                return false;
            }

            // 代理商扣款记录
            $payAmount = Db::name('agent_balance_log')
                ->where('type', BALANCE_FILM_EXPENSE)
                ->where('quote_id', $order['id'])
                ->value('amount');
            // 代理商退款记录
            $refund = Db::name('agent_balance_log')
                ->where('type', BALANCE_FILM_REFUND)
                ->where('quote_id', $order['id'])
                ->value('id');
            // 有扣款，没退款，就开始退
            if ($payAmount && empty($refund)) {
                $payAmount = abs($payAmount);
                if ($payAmount != $order['sale_price']) {
                    Db::rollback();
                    $this->error = '退款金额有误';
                    return false;
                }

                $balance = Db::name('agent')
                    ->where('id', $order['agent_id'])
                    ->value('balance');
                $newBalance = $balance + $payAmount;
                Db::name('agent')
                    ->where('id', $order['agent_id'])
                    ->inc('balance', $payAmount)
                    ->update([
                        'balance_last_updated_at' => date('Y-m-d H:i:s'),
                    ]);
                Db::name('agent_balance_log')
                    ->insert([
                        'agent_id' => $order['agent_id'],
                        'type' => BALANCE_FILM_REFUND,
                        'amount' => $payAmount,
                        'old_balance' => $balance,
                        'new_balance' => $newBalance,
                        'remark' => '出票失败退款：' . fen2yuan($payAmount) . ' 元。订单号：' . $order['order_id'],
                        'quote_id' => $order['id'],
                        'trade_no' => $order['order_id'],
                    ]);
            }
            if ($order['order_from'] == ORDER_FROM_H5) {
                Db::name('movie_pay_log')
                    ->where('id', $payLog['id'])
                    ->inc('refund_amount', $refundFee)
                    ->update();
            }

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();

            $this->error = '退款失败：' . $e->getMessage();

            return false;
        }

        return true;
    }

    /**
     * 微信退款.
     */
    private function wxpayRefund($payLog)
    {
        try {
            $type = 'wechat';
            if (SETTLE_TYPE_PREPAY == $payLog['settle_type']) {
                $agentId = $payLog['agent_id'];
            } else {
                $agentId = 0;
                if ('MWEB' == $payLog['trade_type']) {
                    $type = 'wechat_mweb';
                }
            }
            $wxpay = new \app\common\model\WxpayV2($agentId, $type, 'movie');
            $data = [
                'transactionId' => $payLog['trade_no'],
                'refundNumber' => $payLog['order_id'],
                'totalFee' => $payLog['real_pay_price'],
                'refundFee' => $payLog['refund_fee'],
                'desc' => '出票失败退款',
            ];
            print_r($data);
            $res = $wxpay->refund($data);
        } catch (\Exception $e) {
            $this->error = $e->getMessage();

            return false;
        }

        if (!isset($res['result_code']) || 'SUCCESS' != $res['result_code']) {
            $this->error = '退款失败：' . json_encode($res, JSON_UNESCAPED_UNICODE);

            return false;
        }

        return true;
    }

    /**
     * 佣金结算
     */
    public function settle($order)
    {
        if (2 != $order['status']) {
            $this->error = '该订单尚未支付';

            return false;
        }
        if (5 != $order['supplier_status']) {
            $this->error = '出票成功的订单才能结算【' . $order['supplier_status'] . '】';

            return false;
        }
        if (2 != $order['settle_status']) {
            $this->error = '结算状态有误【' . $order['settle_status'] . '】';

            return false;
        }

        Db::startTrans();
        try {
            $profitBalance = Db::name('agent')
                ->where('id', $order['agent_id'])
                ->value('profit_balance');
            Db::name('agent')
                ->where('id', $order['agent_id'])
                ->inc('profit_balance', $order['profit'])
                ->inc('total_profit', $order['profit'])
                ->update([
                    'balance_last_updated_at' => date('Y-m-d H:i:s'),
                ]);
            $settlePrice = $order['sale_price'] - $order['profit'];
            Db::name('agent_balance_log')
                ->insert([
                    'agent_id' => $order['agent_id'],
                    'type' => BALANCE_FILM_COMMISS,
                    'amount' => $order['profit'],
                    'old_balance' => $profitBalance,
                    'new_balance' => $profitBalance + $order['profit'],
                    'remark' => '影票：' . $order['film_name'] . '，销售价：' . fen2yuan($order['sale_price']) . '元，结算价：' . fen2yuan($settlePrice) . '元，利润：' . fen2yuan($order['profit']) . '元。订单号：' . $order['order_id'],
                    'quote_id' => $order['id'],
                    'trade_no' => $order['order_id'],
                ]);
            Db::name('movie_order')
                ->where('id', $order['id'])
                ->update([
                    'settle_status' => 3,
                    //添加结算时间
                    'settle_time'   => time(),
                ]);

            // 出票成功，插入财务明细
            FinanceStat::addSuccessRecord([
                'order_id' => $order['order_id'],
                'order_type' => PRODUCT_FILM_SERV,
                'settle_type' => $order['settle_type'],
                'profit' => $order['profit'],
                'platform_profit' => $order['platform_profit'],
                'agent_id' => $order['agent_id'],
                'supplier_id' => $order['supplier_id'],
                'amount' => $order['total_net_price'],
                'sale_price' => $order['sale_price'],
                'settle_price' => $order['supplier_price'] + $order['platform_profit'],
                'supplier_price' => $order['supplier_price'],
                'remark' => '出票成功',
            ]);

            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();

            $this->error = '影票佣金结算报错了：' . $e->getMessage();

            return false;
        }

        return true;
    }

    public function getError()
    {
        return $this->error;
    }
}
